﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Reflection;

namespace RTUDataAcquisition.AppCode
{
    public class TransData
    {
        /// 从字符串转换到16进制表示的字符串
        /// 编码,如"utf-8","gb2312"
        /// 是否每字符用逗号分隔
        public static string ToHex(string s, string charset, bool fenge)
        {
            if ((s.Length % 2) != 0)
            {
                s += " ";//空格
                         //throw new ArgumentException("s is not valid chinese string!");
            }
            System.Text.Encoding chs = System.Text.Encoding.GetEncoding(charset);
            byte[] bytes = chs.GetBytes(s);
            string str = "";
            for (int i = 0; i < bytes.Length; i++)
            {
                str += string.Format("{0:X}", bytes[i]);
                if (fenge && (i != bytes.Length - 1))
                {
                    str += string.Format("{0}", ",");
                }
            }
            return str.ToLower();
        }

        /// 从16进制转换成utf编码的字符串
        /// 编码,如"utf-8","gb2312"
        public static string UnHex(string hex, string charset)
        {
            if (hex == null)
                throw new ArgumentNullException("hex");
            hex = hex.Replace(",", "");
            hex = hex.Replace("\n", "");
            hex = hex.Replace("\\", "");
            hex = hex.Replace(" ", "");
            if (hex.Length % 2 != 0)
            {
                hex += "20";//空格
                throw new ArgumentException("hex is not a valid number!", "hex");
            }
            // 需要将 hex 转换成 byte 数组。
            byte[] bytes = new byte[hex.Length / 2];
            for (int i = 0; i < bytes.Length; i++)
            {
                try
                {
                    // 每两个字符是一个 byte。
                    bytes[i] = byte.Parse(hex.Substring(i * 2, 2),
                    System.Globalization.NumberStyles.HexNumber);
                }
                catch
                {
                    // Rethrow an exception with custom message.
                    throw new ArgumentException("hex is not a valid hex number!", "hex");
                }
            }
            System.Text.Encoding chs = System.Text.Encoding.GetEncoding(charset);
            return chs.GetString(bytes);
        }

        /// <summary>
        /// 16进制原码字符串转字节数组
        /// </summary>
        /// <param name="hexString">"AABBCC"或"AA BB CC"格式的字符串</param>
        /// <returns></returns>
        public static byte[] ConvertHexStringToBytes(string hexString)
        {
            hexString = hexString.Replace(" ", "");
            if (hexString.Length % 2 != 0)
            {
                throw new ArgumentException("参数长度不正确");
            }

            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
            {
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            }

            return returnBytes;
        }

        /**  
   * 将int数值转换为占四个字节的byte数组，本方法适用于(高位在前，低位在后)的顺序。  和bytesToInt2（）配套使用 
   */
        public static byte[] intToBytes(int value)
        {
            byte[] src = new byte[4];
            src[0] = (byte)((value >> 24) & 0xFF);
            src[1] = (byte)((value >> 16) & 0xFF);
            src[2] = (byte)((value >> 8) & 0xFF);
            src[3] = (byte)(value & 0xFF);
            return src;
        }

        public static int GetEssDataLength(byte b)
        {
            return b >> 3;
        }

        public static int GetEssDataPointLength(byte b)
        {
            return b & 7;
        }


         public static int CRC16(byte[] p, int datalen)
        {
            byte CRC16Lo, CRC16Hi, CL, CH, SaveHi, SaveLo;
            CRC16Lo = 0xFF; 
            CRC16Hi = 0xFF;
            CL = 0x01; 
            CH = 0xA0;

            for (int i = 0; i < datalen; i++)
            {
                CRC16Lo ^= p[i];                  //每一个数据与CRC寄存器进行异或
                for (int Flag = 0; Flag < 8; Flag++)
                {
                    SaveHi = CRC16Hi; 
                    SaveLo = CRC16Lo;
                    CRC16Hi >>= 1; 
                    CRC16Lo >>= 1;   //高位右移一位，低位右移一位

                    if ((SaveHi & 0x01) == 0x01)     //如果高位字节最后一位为1
                        CRC16Lo |= 0x80;                //则低位字节右移后前面补1否则自动补0

                    if ((SaveLo & 0x01) == 0x01)     //如果LSB为1，则与多项式码进行异或
                    { CRC16Hi ^= CH; CRC16Lo ^= CL; }
                }
            }
            return (int)(CRC16Hi << 8) | CRC16Lo;
        }


        ////字符串转BCD码方法
        //public static Byte[] StringToBCD(string strTemp)
        //{
        //    try
        //    {
        //        if (Convert.ToBoolean(strTemp.Length & 1))//若字符串的长度为奇数，则变为偶数 
        //        {
        //            strTemp = "0" + strTemp;//数位为奇数时前面补0  
        //        }
        //        Byte[] aryTemp = new Byte[strTemp.Length / 2];
        //        for (int i = 0; i < (strTemp.Length / 2); i++)
        //        {
        //            aryTemp[i] = (Byte)(((strTemp[i * 2] - '0') << 4) | (strTemp[i * 2 + 1] - '0'));//两个字节的数组成一个字节的BCD码0-9
        //                                                                                            // aryTemp[i] = (Byte)(((strTemp[i * 2])<< 4) | (strTemp[i * 2 + 1]));
        //        }
        //        return aryTemp;//高位在前  
        //    }
        //    catch
        //    {
        //        return null;
        //    }
        //}

        ///// <summary>  
        ///// BCD码转换16进制(压缩BCD)  
        ///// </summary>  
        ///// <param name="strTemp"></param>  
        ///// <returns></returns>  
        //public static Byte[] StringToBCD(string strTemp, int IntLen)
        //{
        //    try
        //    {
        //        Byte[] Temp = StringToBCD(strTemp.Trim());
        //        Byte[] return_Byte = new Byte[IntLen];
        //        if (IntLen != 0)
        //        {
        //            if (Temp.Length < IntLen)
        //            {
        //                for (int i = 0; i < IntLen - Temp.Length; i++)
        //                {
        //                    return_Byte[i] = 0x00;
        //                }
        //            }
        //            Array.Copy(Temp, 0, return_Byte, IntLen - Temp.Length, Temp.Length);
        //            return return_Byte;
        //        }
        //        else
        //        {
        //            return Temp;
        //        }
        //    }
        //    catch
        //    { return null; }
        //}
        ///// <summary>  
        ///// 16进制转换BCD（解压BCD）  
        ///// </summary>  
        ///// <param name="data"></param>  
        ///// <returns></returns>  
        //public static string BCDToString(Byte[] data)
        //{
        //    try
        //    {
        //        StringBuilder sb = new StringBuilder(data.Length * 2);
        //        foreach (Byte b in data)
        //        {
        //            sb.Append(b >> 4);
        //            sb.Append(b & 0x0f);
        //        }
        //        return sb.ToString();
        //    }
        //    catch { return string.Empty; }
        //}

        ///// <summary>  
        ///// 16进制转换BCD（解压BCD）  
        ///// </summary>  
        ///// <param name="data"></param>  
        ///// <returns></returns>  
        //public static float? BCDToInt(Byte[] data, int intPoint)
        //{
        //    try
        //    {
        //        long value = Convert.ToInt64(BCDToString(data));
        //        if (intPoint != 0)
        //        {
        //            return value / 10 * intPoint;
        //        }
        //        return value;
        //    }
        //    catch { return null; }
        //}

        public static string ConvertData(Byte[] data)
        {
            try
            {
                StringBuilder sb = new StringBuilder();
                if (data != null)
                {
                    foreach (Byte b in data)
                    {
                        sb.Append(Convert.ToString(b, 16).ToUpper().PadLeft(2, '0'));
                    }
                }
                return sb.ToString();
            }
            catch { return string.Empty; }
        }


        public static string ConvertDataBySpace(Byte[] data)
        {
            try
            {
                StringBuilder sb = new StringBuilder();
                foreach (Byte b in data)
                {
                    sb.Append(Convert.ToString(b, 16).ToUpper().PadLeft(2, '0') + " ");
                }
                return sb.ToString().Trim();
            }
            catch { return string.Empty; }
        }

        public static double? ConvertData(Byte[] data, int intPoint)
        {
            try
            {
                long value = Convert.ToInt64(ConvertData(data));
                if (intPoint != 0)
                {
                    return value / Math.Pow(10.0, intPoint);
                }
                return value;
            }
            catch { return null; }
        }

        /// <summary>  
        /// byte转16进制字符串  
        /// </summary>  
        /// <param name="data"></param>  
        /// <returns></returns>  
        public static string ByteToStringH(Byte data)
        {
            try
            {
                return data.ToString("X").PadLeft(2, '0') + "H";
                //Convert.ToString(data, 16).PadLeft(2, '0').ToUpper() + "H";
            }
            catch { return string.Empty; }
        }

        public static int ConvertNum(byte b1, byte b2)
        {
            try
            {
                int intNum = b1;
                intNum = intNum << 8;
                intNum = intNum | b2;
                return intNum & 0xFFF;
            }
            catch { return 0; }
        }

        /// <summary>
        /// 获取多包数据总包数和序列号，必须为3字节
        /// </summary>
        /// <param name="byteData">3字节数据</param>
        /// <param name="totalPackages">总包数</param>
        /// <param name="indexPackages">包数序列号</param>
        public static void GetTotalPackageAndSerialNumber(byte[] byteData, ref int totalPackages, ref int indexPackages)
        {
            try
            {
                if (byteData.Length != 3)
                {
                    return;
                }

                StringBuilder s = new StringBuilder();
                for (int i = 0; i < byteData.Length; i++)
                {
                    s.Append(Convert.ToString(byteData[i], 2).PadLeft(8,'0'));
                }

                totalPackages = Convert.ToInt32(s.ToString().Substring(0, 12), 2);
                indexPackages = Convert.ToInt32(s.ToString().Substring(12), 2);
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }

        ///// <summary>  
        ///// BCD转日期格式字符串  
        ///// </summary>  
        ///// <param name="data"></param>  
        ///// <returns></returns>  
        //public static string BCDToDateString(Byte[] data)
        //{
        //    try
        //    {
        //        if (data.Length != 6 && data.Length != 5)
        //        {
        //            return string.Empty;
        //        }

        //        string strTime = string.Empty;
        //        if (data.Length == 6)
        //        {
        //            strTime = DateTime.Now.Year.ToString().Substring(0, 2) + BCDToString(data);
        //            strTime = strTime.Substring(0, 4) + "-" + strTime.Substring(4, 2) + "-" + strTime.Substring(6, 2) + " " + strTime.Substring(8, 2) + ":" + strTime.Substring(10, 2) + ":" + strTime.Substring(12, 2);
        //        }
        //        else
        //        {
        //            strTime = DateTime.Now.Year.ToString().Substring(0, 2) + BCDToString(data) + "00";
        //            strTime = strTime.Substring(0, 4) + "-" + strTime.Substring(4, 2) + "-" + strTime.Substring(6, 2) + " " + strTime.Substring(8, 2) + ":" + strTime.Substring(10, 2) + ":" + strTime.Substring(12, 2);
        //        }
        //        return strTime;

        //    }
        //    catch { return string.Empty; }
        //}

        /// <summary>  
        /// 数据转日期格式字符串  
        /// </summary>  
        /// <param name="data"></param>  
        /// <returns></returns>  
        public static string DataToDateString(Byte[] data)
        {
            try
            {
                if (data.Length != 6 && data.Length != 5)
                {
                    return string.Empty;
                }

                string strTime = string.Empty;
                if (data.Length == 6)
                {
                    strTime = DateTime.Now.Year.ToString().Substring(0, 2) + ConvertData(data);
                    strTime = strTime.Substring(0, 4) + "-" + strTime.Substring(4, 2) + "-" + strTime.Substring(6, 2) + " " + strTime.Substring(8, 2) + ":" + strTime.Substring(10, 2) + ":" + strTime.Substring(12, 2);
                }
                else
                {
                    strTime = DateTime.Now.Year.ToString().Substring(0, 2) + ConvertData(data) + "00";
                    strTime = strTime.Substring(0, 4) + "-" + strTime.Substring(4, 2) + "-" + strTime.Substring(6, 2) + " " + strTime.Substring(8, 2) + ":" + strTime.Substring(10, 2) + ":" + strTime.Substring(12, 2);
                }
                return strTime;

            }
            catch { return string.Empty; }
        }

        /// <summary>
        /// DataTable转为List【T】
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="table"></param>
        /// <returns>List【T】</returns>
        public static List<T> GetList<T>(DataTable table)
        {
            List<T> list = new List<T>();
            T t = default(T);
            PropertyInfo[] propertypes = null;
            string tempName = string.Empty;
            foreach (DataRow row in table.Rows)
            {
                t = Activator.CreateInstance<T>();
                propertypes = t.GetType().GetProperties();
                foreach (PropertyInfo pro in propertypes)
                {
                    tempName = pro.Name;
                    if (table.Columns.Contains(tempName))
                    {
                        object value = row[tempName];
                        if (value.GetType() == typeof(System.DBNull))
                        {
                            value = null;
                        }
                        if (value != null)
                        {
                            pro.SetValue(t, value, null);
                        }
                    }
                }
                list.Add(t);
            }
            return list;
        }
    }
}
